using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Windows;
using System.Linq;

namespace TwoPageView3
{
    public class TpvDirectoryInfo : ITpvDirectoryInfo
    {
        private DirectoryInfo mDirectoryInfo;
        private bool mExists;
        private readonly string mFullName;
        private readonly string mFileName;
        private static ReaderWriterLock mLock = new ReaderWriterLock();

        /// <summary>
        /// ctor for directory (or PDF file as directory)
        /// </summary>
        /// <param name="path"></param>
        private TpvDirectoryInfo(string path) {
            mFullName = path;
            mFileName = Path.GetFileName(mFullName);
            mDirectoryInfo = new DirectoryInfo(mFullName);
            if (null != mDirectoryInfo && mDirectoryInfo.Exists) {
                mExists = true;
            }
        }

        public static TpvDirectoryInfo Factory(string path) {
            var result = new TpvDirectoryInfo(path);
            if (result == null || !result.mExists) {
                return null;
            }
            return result;
        }

        public  bool HasSubDirectory() {
            if (null == mDirectoryInfo) {
                return false;
            }

            try {
                var subDirectoryEnumerator = mDirectoryInfo.EnumerateDirectories().GetEnumerator();
                if (subDirectoryEnumerator.MoveNext()) {
                    // at least one subdirectory exists.
                    return true;
                }

                var pdfFileEnumerator = mDirectoryInfo.EnumerateFiles("*.pdf").GetEnumerator();
                if (pdfFileEnumerator.MoveNext()) {
                    // at least one pdf file exists.
                    return true;
                }
            } catch (UnauthorizedAccessException) {
                return false;
            }
            return false;
        }

        public bool IsPdf() {
            return false;
        }

        public  string Name {
            get { return mFileName; }
        }

        public  string FullName {
            get { return mFullName; }
        }

        public IEnumerable<ITpvDirectoryInfo> EnumerateDirectories() {
            if (null == mDirectoryInfo) {
                yield break;
            }

            var subDirs = mDirectoryInfo.EnumerateDirectories();
            foreach (DirectoryInfo d in subDirs) {
                var di = TpvDirectoryInfo.Factory(TpvUtility.PathNormalize(mFullName + Path.DirectorySeparatorChar + d.Name));
                if (di != null) {
                    yield return di;
                }
            }
            var itemSearch = from FileInfo item in mDirectoryInfo.EnumerateFiles()
                             where String.Compare(item.Extension, ".pdf", StringComparison.OrdinalIgnoreCase) == 0
                             select item;
            foreach (var fi in itemSearch) {
                ITpvDirectoryInfo x = TpvPdfDirectoryInfo.Factory(
                        TpvUtility.PathNormalize(mFullName + Path.DirectorySeparatorChar + fi.Name));
                yield return x;
            }
        }

        // called from the background thread
        public  IEnumerable<TpvFileInfo> EnumerateImageFiles() {
            if (null == mDirectoryInfo) {
                return null;
            }
            int fileNumber = 0;
            IEnumerable<TpvFileInfo> result = null;
            try {
                result = mDirectoryInfo.EnumerateFiles()
                        .Where(s => ((s.FullName.ToLower().EndsWith(".png")) ||
                                     (s.FullName.ToLower().EndsWith(".jpg"))))
                        .Select(s => new TpvFileInfo(s.FullName, s.FullName, fileNumber++, s.Length, s.LastWriteTimeUtc));
            } catch (DirectoryNotFoundException) {
                result = null;
            }
            return result;
        }
    }
}
